package com.ali.common;

import javax.crypto.Cipher;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.PBEParameterSpec;
import java.nio.charset.StandardCharsets;
import java.security.Key;
import java.security.SecureRandom;

public class PbeUtil {
    private static final String ALGORITHM_MD5ANDDES = "PBEWITHMD5andDES";

    private static final int ITERATIONCOUNT_100 = 100;

    /**
     * 获取Salt
     */
    public static String getSalt() {
        SecureRandom secureRandom = new SecureRandom();
        byte[] saltByte = secureRandom.generateSeed(8);
        return Base64Util.encrypt(saltByte);
    }

    /***
     * 获取Key
     */
    public static Key getKey(String password) {
        try {
            PBEKeySpec pbeKeySpec = new PBEKeySpec(password.toCharArray());
            SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance(ALGORITHM_MD5ANDDES);
            return secretKeyFactory.generateSecret(pbeKeySpec);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * PBE加密
     */
    public static String encrypt(String content, Key key, String salt) {
        byte[] contentByte = content.getBytes(StandardCharsets.UTF_8);

        try {
            Cipher cipher = getCipher(key, salt, Cipher.ENCRYPT_MODE);
            byte[] doFinalByte = cipher.doFinal(contentByte);
            return Base64Util.encrypt(doFinalByte);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 获取Cipher
     */
    private static Cipher getCipher(Key key, String salt, int opmode) {
        try {
            byte[] saltByte = Base64Util.getByteByDecrypt(salt);

            Cipher cipher = Cipher.getInstance(ALGORITHM_MD5ANDDES);
            PBEParameterSpec pbeParameterSpec = new PBEParameterSpec(saltByte, ITERATIONCOUNT_100);
            cipher.init(opmode, key, pbeParameterSpec);
            return cipher;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * PBE解密
     */
    public static String decrypt(String encryptStr, Key key, String salt) {
        try {
            byte[] encryptStrByte = Base64Util.getByteByDecrypt(encryptStr);

            Cipher cipher = getCipher(key, salt, Cipher.DECRYPT_MODE);
            byte[] doFinalByte = cipher.doFinal(encryptStrByte);
            return new String(doFinalByte, StandardCharsets.UTF_8);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}